/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+                                                                   +
+  reformat.c - implements the verification stage                   +
+                                                                   +
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ macros								                            + 
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

#include "common.h"

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
+ function definitions                                              +
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

/*
	re-format bytecode numeric operands to native 
	( prevents redundant runtime work ).

	This also performs verification to make sure that:
	1) instruction opcodes are valid
	2) register arguments are actual registers of necessary type
	3) immediate address values are in range [ 0 , $TOP ]
	4) Haven't prematurely hit end of bytecode instruction
*/
U1 reformat()
{
//	U4 current_byte;
	U4 stop;

	//current_byte = GetMemoryAddress(R[$CS],R[$IP]);
	stop=GetMemoryAddress(LoadPosition+PSP,0)+appMetaData.bSizeLoadedModule;
	DBG_FMT2("start=0x%04X,stop=0x%04X\n",GetMemoryAddress(R[$CS],R[$IP]),stop);

	R[$AX]=0x1234;
	R[$BX]=0x5678;
	R[$CX]=0x9abc;
	R[$DX]=0xdef0;

	printf("RAM[IF_PREFIX]=0x%x,RAM[MEM_PREFIX]=0x%x\n",RAM[IF_PREFIX],RAM[MEM_PREFIX]);
	//test1=GetMemoryU2(R[$CS],R[$IP]);
	//printf("test1=0x%x,(U1)test1=0x%x,(U1)R[$AX]=0x%x\n",test1,(U1)test1,(U1)R[$AX]);
	
//	printf("$AX=0x%x,R_AH=0x%x,R_AL=0x%x\n",$AX,R_AH,R_AL);
//	R[$AX]=0xabcd;
//	printf("R[$AX]=0x%x,[$AH]=0x%x,[$AL]=0x%x\n",R[$AX],$AH,$AL);
//	SetReg8(CL,0x99);
//	printf("R[$CX]=0x%x,[$CH]=0x%x,[$CL]=0x%x\n",R[$CX],$CH,$CL);
//	printf("$AL=0x%x,AL=0x%x\n",GetReg8(0x00, 6,1),GetReg8(0x00, 6,0));

/*
//	printf("111111111\n");
	SetFlagsByInstruction(ADD_AL_IMM,0x007f,0x0024);
//	printf("222222222\n");
	SetFlagsByInstruction(ADD_AL_IMM,0x0080,0x00AF);

	printf("111111111\n");
	SetFlagsByInstruction(ADD_AX_IMM,0x7fff,0x7fff);
	printf("222222222\n");
	SetFlagsByInstruction(ADD_AX_IMM,0x1234,0x8899);
	SetFlagsByInstruction(ADD_AX_IMM,0x8000,0x8000);
	SetFlagsByInstruction(ADD_AX_IMM,0x1000,0x2340);
*/	
	while(GetMemoryAddress(R[$CS],R[$IP]) < stop)
	{
		RAM[IF_ONLY_NUM]=0;
		GetCode();
		R[$IP]++;
		printBasicRegisters();
		printf("\n\n");
	}

	DBG_FMT0("reformatting complete\n");

	return(TRUE);

}/*end reformat*/

/*-----------------------------------------------------------------*/

/* 
some registers are read-only ( used by runtime system only )
*/

/*void badIntReg(U1 arg, U8 currentbyte)
{
	if(arg>$R24)
	{ 
		ERROR1_LVL2("badIntReg(): (%d) not integer register",arg);
		
		xmlBegin();
		fprintf(errPtr,"badIntReg(): bad register at address "); 
		fpU8(errPtr,currentbyte); 
		xmlEnd();

		FATAL_ERROR();
	}
	return;

}end badIntReg*/

/*-----------------------------------------------------------------

void badFltReg(U1 arg, U8 currentbyte)		
{
	if(arg>$F10) 
	{ 
		ERROR1_LVL2("badFltReg(): (%d) not float register",arg);

		xmlBegin();
		fprintf(errPtr,"badFltReg(): bad register at address "); 
		fpU8(errPtr,currentbyte); 
		xmlEnd();
		
		FATAL_ERROR();
	} 
	return;

}end badFltReg*/

/*-----------------------------------------------------------------

void badDblReg(U1 arg, U8 currentbyte)		
{
	if(arg>$D10) 
	{ 
		ERROR1_LVL2("badDblReg(): (%d) not double register",arg);

		xmlBegin();
		fprintf(errPtr,"badDblReg(): bad register at address "); 
		fpU8(errPtr,currentbyte); 
		xmlEnd();
		
		FATAL_ERROR();
	} 
	return;

}/*end badDblReg*/

/*
void checkAddress(U1 *arr, U8 cb)
{
	U8* addr; 
	addr = (U8*)&arr[cb]; 
	if(*addr > R[$TOP])
	{ 
		ERROR0_LVL2("checkAddress(): address out of bounds");

		xmlBegin(); 
		fprintf(errPtr,"checkAddress(): invalid address literal ");
		fpU8(errPtr,*addr);
		fprintf(errPtr," at memory location "); 
		fpU8(errPtr,cb); 
		xmlEnd();

		FATAL_ERROR();
	}
	return;

}end checkAddress*/ 

/*-----------------------------------------------------------------*/

/* 
don't want incomplete instruction (hit end bytecode before end 
of instruction) 
*/

void checkCurrentByte(U8 cb, U8 end)
{
	if(cb>=end)
	{ 
		ERROR0_LVL2("checkCurrentByte(): incomplete instruction"); 

		xmlBegin(); 
		fprintf(errPtr,"checkCurrentByte(): ");
		fprintf(errPtr,"incomplete instruction at address "); 
		fpU8(errPtr,cb); 
		xmlEnd();

		FATAL_ERROR(); 
	}
	return;

}/*end checkCurrentByte*/

/*-----------------------------------------------------------------*/

/* 
last byte of an instruction is allowed to be at end of bytecode, so 
use checkEndCurrentByte 
*/

void checkEndCurrentByte(U8 cb, U8 end)
{
	if(cb>end)
	{ 
		ERROR0_LVL2("checkEndCurrentByte(): incomplete instruction"); 
		
		xmlBegin(); 
		fprintf(errPtr,"checkEndCurrentByte(): ");
		fprintf(errPtr,"incomplete instruction at address "); 
		fpU8(errPtr,cb); 
		xmlEnd();

		FATAL_ERROR(); 
	}
	return;

}/*end checkEndCurrentByte*/

/*-----------------------------------------------------------------

void badAddress(U8 arg, U8 currentbyte)
{	
	if(arg>R[$TOP]) 
	{ 
		ERROR0_LVL2("badAddress(): invalid address literal");
		
		xmlBegin();
		fprintf(errPtr,"badAddress(): invalid address literal ");
		fpU8(errPtr,arg); 
		fprintf(errPtr," at memory location "); 
		fpU8(errPtr,currentbyte); 
		xmlEnd();

		FATAL_ERROR();
	}
	return;

}end badAddress*/

/*-----------------------------------------------------------------

void badStack(U8 arg, U8 currentbyte)
{
	if(arg<=R[$HE]) 
	{ 
		ERROR0_LVL2("badStack(): stack overflow into heap");

		xmlBegin();
		fprintf(errPtr,"badStack(): ");
		fpU8(errPtr,arg); 
		fprintf(errPtr," stack overflow into heap "); 
		fprintf(errPtr,"at address "); 
		fpU8(errPtr,currentbyte); 
		xmlEnd();

		FATAL_ERROR();
	}
	else if(arg>R[$TOP])
	{
		ERROR0_LVL2("badStack(): stack underflow beyond $TOP");

		xmlBegin();
		fprintf(errPtr,"badStack(): ");
		fpU8(errPtr,arg); 
		fprintf(errPtr," stack underflow beyond $TOP "); 
		fprintf(errPtr,"at address "); 
		fpU8(errPtr,currentbyte); 
		xmlEnd();

		FATAL_ERROR();
	}
	return;

}end badStack*/ 	

/*-----------------------------------------------------------------

void badHeap(U8 arg, U8 currentbyte)
{
	if(arg<R[$HS]) 
	{ 
		ERROR0_LVL2("badHeap(): below heap");

		xmlBegin();
		fprintf(errPtr,"badHeap(): ");
		fpU8(errPtr,arg); 
		fprintf(errPtr," below start of heap "); 
		fprintf(errPtr,"at address "); 
		fpU8(errPtr,currentbyte); 
		xmlEnd();

		FATAL_ERROR();
	}
	else if(arg>R[$HE])
	{
		ERROR0_LVL2("badHeap(): beyond end of heap");

		xmlBegin();
		fprintf(errPtr,"badHeap(): ");
		fpU8(errPtr,arg); 
		fprintf(errPtr," beyond end of heap "); 
		fprintf(errPtr,"at address "); 
		fpU8(errPtr,currentbyte); 
		xmlEnd();

		FATAL_ERROR();

	}
	return;

}end badHeap*/ 	
